/**
 * 
 */

package com.chengyu.eyc.service;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.chengyu.eyc.constant.EycConstants;
import com.chengyu.eyc.enums.ConfigTypeEnum;
import com.chengyu.eyc.enums.OrderStatusEnum;
import com.chengyu.eyc.enums.PayStatusEnum;
import com.chengyu.eyc.exception.GenericException;
import com.chengyu.eyc.mapper.EycInspPriceRuleMapper;
import com.chengyu.eyc.mapper.EycOrderMapper;
import com.chengyu.eyc.mapper.EycUserMapper;
import com.chengyu.eyc.mapper.EycVehicleFileMapper;
import com.chengyu.eyc.model.EycInspPriceRule;
import com.chengyu.eyc.model.EycInspStation;
import com.chengyu.eyc.model.EycOrder;
import com.chengyu.eyc.model.EycUser;
import com.chengyu.eyc.model.EycVehicleFile;
import com.chengyu.eyc.utils.RegexUtils;
import com.chengyu.eyc.utils.SeqNumUtil;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.page.PageMethod;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import tk.mybatis.mapper.entity.Condition;
import tk.mybatis.mapper.entity.Example.Criteria;

/**
 * @author kevin
 *
 */
@Transactional
@Service
public class EycServiceImpl implements EycService {

    @Autowired
    EycBaseService eycBaseService;

    @Autowired
    EycUserMapper eycUserMapper;

    @Autowired
    EycVehicleFileMapper eycVehicleFileMapper;

    @Autowired
    EycOrderMapper eycOrderMapper;

    @Autowired
    EycInspPriceRuleMapper eycInspPriceRuleMapper;

    /**
     * @see com.chengyu.eyc.service.EycService#cancelOrder(java.lang.String, java.lang.String)
     */
    @Override
    public EycOrder cancelOrder(String orderNum, String userId) {
        EycOrder eycOrder = new EycOrder();
        eycOrder.setOrderNum(orderNum);
        eycOrder.setUserId(userId);
        eycOrder = this.eycOrderMapper.selectOne(eycOrder);
        eycOrder.setStatus(OrderStatusEnum.CANCEL.getCode());
        eycOrder.setCancelTime(new Date());
        this.eycOrderMapper.updateByPrimaryKey(eycOrder);
        if (StrUtil.isNotBlank(eycOrder.getCouponId())) {
            this.eycBaseService.updateCouponIsUsed(eycOrder.getCouponId(), Boolean.FALSE);
        }
        return eycOrder;
    }

    private boolean checkVehicleFileUnique(EycVehicleFile eycVehicleFile) {
        Condition condition = new Condition(EycVehicleFile.class, true, true);
        Criteria criteria = condition.createCriteria();
        criteria.andEqualTo("userId", eycVehicleFile.getUserId()).andEqualTo("plateNum", eycVehicleFile.getPlateNum()).andEqualTo("isActive", Boolean.TRUE);
        if (!StrUtil.isBlank(eycVehicleFile.getVehicleFileId())) {
            criteria.andNotEqualTo("vehicleFileId", eycVehicleFile.getVehicleFileId());
        }
        return this.eycVehicleFileMapper.selectCountByCondition(condition) == 0;
    }

    /**
     * @see com.chengyu.eyc.service.EycService#deleteVehicleFile(com.chengyu.eyc.model.EycVehicleFile)
     */
    @Override
    public Boolean deleteVehicleFile(EycVehicleFile eycVehicleFile) {
        eycVehicleFile.setIsActive(Boolean.FALSE);
        this.eycVehicleFileMapper.updateByPrimaryKey(eycVehicleFile);
        return Boolean.TRUE;
    }
    /**
     * @see com.chengyu.eyc.service.EycService#searchEycVehicleFileByPlateNum(java.lang.String, java.lang.String)
     */
    @Override
    public EycVehicleFile searchEycVehicleFileByPlateNum(String userId, String plateNum) {
        Condition condition = new Condition(EycVehicleFile.class, true, true);
        Criteria criteria = condition.createCriteria();
        criteria.andEqualTo("userId", userId).andEqualTo("plateNum", plateNum).andEqualTo("isActive", Boolean.TRUE);
        List<EycVehicleFile> eycVehicleFiles = this.eycVehicleFileMapper.selectByCondition(condition);
        return CollUtil.isNotEmpty(eycVehicleFiles) ? eycVehicleFiles.get(0) : null;
    }

    /**
     * @see com.chengyu.eyc.service.EycService#exportOrder(java.util.Map)
     */
    @Override
    public List<Map<String, Object>> exportOrder(Map<String, Object> params) {
        params.put("isExport", Boolean.TRUE);
        return this.eycOrderMapper.searchOrders(params);
    }

    private String getUserIdByPhoneNumber(String phoneNumber) {
        Condition condition = new Condition(EycUser.class, true, true);
        condition.createCriteria().andEqualTo("phoneNumber", phoneNumber);
        List<EycUser> eycUsers = this.eycUserMapper.selectByCondition(condition);
        return CollUtil.isNotEmpty(eycUsers) ? eycUsers.get(0).getUserId() : RandomStringUtils.randomNumeric(10);
    }

    /**
     * 生产订单
     * 
     * @param eycOrder
     * @return
     */
    @Override
    public EycOrder insertOrder(EycOrder eycOrder) {
        if (!RegexUtils.isMobile(eycOrder.getContactNum())) {
            throw new GenericException("请填写正确的手机号码~~");
        }
        eycOrder.setStatus(OrderStatusEnum.SUBMITED.getCode());
        eycOrder.setPayStatus(PayStatusEnum.UNPAID.getCode());
        eycOrder.setOrderNum(SeqNumUtil.genOrderNum());
        this.eycOrderMapper.insert(eycOrder);
        if (StrUtil.isNotBlank(eycOrder.getCouponId())) {
            this.eycBaseService.updateCouponIsUsed(eycOrder.getCouponId(), Boolean.TRUE);
        }
        return eycOrder;
    }

    /**
     * @see com.chengyu.eyc.service.EycService#insertOrUpdateVehicleFile(com.chengyu.eyc.model.EycVehicleFile)
     */
    @Override
    public EycVehicleFile insertOrUpdateVehicleFile(EycVehicleFile eycVehicleFile) {
        if (StrUtil.isBlank(eycVehicleFile.getVehicleType())) {
            Optional.ofNullable(this.eycBaseService.searchConfigByTypeAndNme(ConfigTypeEnum.VEHICLE_TYPE.getCode(), eycVehicleFile.getVehicleTypeNme())).ifPresent(r -> {
                eycVehicleFile.setVehicleType(r.getDcOptions());
            });
        }
        if (StrUtil.isBlank(eycVehicleFile.getUseCharacter())) {
            Optional.ofNullable(this.eycBaseService.searchConfigByTypeAndNme(ConfigTypeEnum.VEHICLE_USE_CHARACTER.getCode(), eycVehicleFile.getUseCharacterNme())).ifPresent(r -> {
                eycVehicleFile.setUseCharacter(r.getDcOptions());
            });
        }
        if (StrUtil.isBlank(eycVehicleFile.getEnergy())) {
            Optional.ofNullable(this.eycBaseService.searchConfigByTypeAndNme(ConfigTypeEnum.VEHICLE_ENERGY.getCode(), eycVehicleFile.getEnergyNme())).ifPresent(r -> {
                eycVehicleFile.setEnergy(r.getDcOptions());
            });
        }
        if (!checkVehicleFileUnique(eycVehicleFile)) {
            throw new GenericException(String.format("车牌【%s】已经维护过，不需要重复维护~~", eycVehicleFile.getPlateNum()));
        }
        if (StrUtil.isBlank(eycVehicleFile.getVehicleFileId())) {
            this.eycVehicleFileMapper.insert(eycVehicleFile);
        } else {
            this.eycVehicleFileMapper.updateByPrimaryKey(eycVehicleFile);
        }
        return eycVehicleFile;
    }

    /**
     * @see com.chengyu.eyc.service.EycService#insertUser(com.chengyu.eyc.model.EycUser)
     */
    @Override
    public EycUser insertUser(EycUser eycUser) {
        EycUser oldEycUser = this.searchEycUserByOpenid(eycUser.getOpenid());
        if (oldEycUser != null) {
            this.eycUserMapper.updateByPrimaryKey(oldEycUser);
            return oldEycUser;
        } else {
            eycUser.setUserId(getUserIdByPhoneNumber(eycUser.getPhoneNumber()));
            this.eycUserMapper.insert(eycUser);
            return eycUser;
        }
    }

    /**
     * @see com.chengyu.eyc.service.EycService#searchEycInspectionStations(java.util.Map)
     */
    @Override
    public List<EycInspStation> searchEycInspectionStations(Map<String, Object> params) {
        return this.eycBaseService.searchEycInspectionStations(params);
    }

    /**
     * @see com.chengyu.eyc.service.EycService#searchEycOrderByOrderNum(java.lang.String)
     */
    @Override
    public EycOrder searchEycOrderByOrderNum(String orderNum) {
        EycOrder eycOrder = new EycOrder();
        eycOrder.setOrderNum(orderNum);
        return this.eycOrderMapper.selectOne(eycOrder);
    }

    private EycUser searchEycUserByOpenid(String openid) {
        EycUser eycUser = new EycUser();
        eycUser.setOpenid(openid);
        return this.eycUserMapper.selectOne(eycUser);
    }

    /**
     * @see com.chengyu.eyc.service.EycService#searchEycUserByUserId(java.lang.String)
     */
    @Override
    public EycUser searchEycUserByUserIdAndUserType(String userId, String userType) {
        EycUser eycUser = new EycUser();
        eycUser.setUserId(userId);
        eycUser.setUserType(userType);
        return this.eycUserMapper.selectOne(eycUser);
    }

    /**
     * @see com.chengyu.eyc.service.EycService#searchEycVehicleFileByUserId(java.lang.String)
     */
    @Override
    public List<EycVehicleFile> searchEycVehicleFileByUserId(String userId) {
        Condition condition = new Condition(EycVehicleFile.class, true, true);
        condition.createCriteria().andEqualTo("userId", userId).andEqualTo("isActive", Boolean.TRUE);
        condition.setOrderByClause("CREATE_TIME desc");
        return this.eycVehicleFileMapper.selectByCondition(condition);
    }

    /**
     * @see com.chengyu.eyc.service.EycService#searchEycVehicleFileCountByUserId(java.lang.String)
     */
    @Override
    public Integer searchEycVehicleFileCountByUserId(String userId) {
        Condition condition = new Condition(EycVehicleFile.class);
        condition.createCriteria().andEqualTo("userId", userId).andEqualTo("isActive", Boolean.TRUE);
        return this.eycVehicleFileMapper.selectCountByCondition(condition);
    }

    /**
     * @see com.chengyu.eyc.service.EycService#searchInspPriceRules(java.util.Map)
     */
    @Override
    public List<EycInspPriceRule> searchInspPriceRules(Map<String, Object> params) {
        return eycInspPriceRuleMapper.selectAll();
    }

    private Integer searchOrderCountByPayStatus(String userId, String payStatus) {
        Condition condition = new Condition(EycOrder.class, true, true);
        condition.createCriteria().andEqualTo("userId", userId).andEqualTo("payStatus", payStatus).andIn("status",
            Arrays.asList(OrderStatusEnum.SUBMITED.getCode(), OrderStatusEnum.CONFIRM.getCode()));
        return this.eycOrderMapper.selectCountByCondition(condition);
    }

    /**
     * @see com.chengyu.eyc.service.EycService#searchOrders(java.util.Map)
     */
    @Override
    public PageInfo<Map<String, Object>> searchOrders(Map<String, Object> params) {
        PageInfo<Map<String, Object>> pageInfo = new PageInfo<>();
        pageInfo.setList(this.eycOrderMapper.searchOrders(params));
        pageInfo.setTotal(this.eycOrderMapper.searchCountOrders(params));
        pageInfo.setPageNum((int)params.get(EycConstants.PAGE_NUMBER));
        return pageInfo;
    }

    /**
     * @see com.chengyu.eyc.service.EycService#searchUncompletedOrderCount(java.lang.String)
     */
    @Override
    public Integer searchUncompletedOrderCount(String userId) {
        return this.searchOrderCountByPayStatus(userId, PayStatusEnum.PAID.getCode());
    }

    /**
     * @see com.chengyu.eyc.service.EycService#searchUnpaidOrderCount(java.lang.String)
     */
    @Override
    public Integer searchUnpaidOrderCount(String userId) {
        return this.searchOrderCountByPayStatus(userId, PayStatusEnum.UNPAID.getCode());
    }

    @Override
    public PageInfo<EycUser> searchUsers(Map<String, Object> params) {
        PageMethod.startPage((int)params.get(EycConstants.PAGE_NUMBER), (int)params.get(EycConstants.PAGE_SIZE));
        Condition condition = new Condition(EycUser.class);
        condition.createCriteria().andEqualTo("userType", params.get("userType"));
        return new PageInfo<>(this.eycUserMapper.selectByCondition(condition));
    }

    /**
     * @see com.chengyu.eyc.service.EycService#sumOrderPreferentialAmountByUserId(java.lang.String)
     */
    @Override
    public BigDecimal sumOrderPreferentialAmountByUserId(String userId) {
        return this.eycOrderMapper.sumOrderPreferentialAmountByUserId(userId);
    }
    
    /**
     * @see com.chengyu.eyc.service.EycService#sumOrderPayAmountByUserId(java.lang.String)
     */
    @Override
    public BigDecimal sumOrderPayAmountByUserId(String userId) {
        return this.eycOrderMapper.sumOrderPayAmountByUserId(userId);
    }

    @Override
    public EycOrder updateEycOrder(EycOrder eycOrder) {
        this.eycOrderMapper.updateByPrimaryKey(eycOrder);
        return eycOrder;
    }

    /**
     * @see com.chengyu.eyc.service.EycService#updateEycVehicleFile(com.chengyu.eyc.model.EycVehicleFile)
     */
    @Override
    public EycVehicleFile updateEycVehicleFile(EycVehicleFile eycVehicleFile) {
        this.eycVehicleFileMapper.updateByPrimaryKey(eycVehicleFile);
        return eycVehicleFile;
    }

    /**
     * @see com.chengyu.eyc.service.EycService#verificationOrder(java.lang.String)
     */
    @Override
    public EycOrder verificationOrder(String orderNum) {
        EycOrder eycOrder = this.searchEycOrderByOrderNum(orderNum);
        if (!StrUtil.equals(eycOrder.getStatus(), OrderStatusEnum.CONFIRM.getCode()) || !StrUtil.equals(eycOrder.getPayStatus(), PayStatusEnum.PAID.getCode())) {
            throw new GenericException(String.format("订单[%s]不满足核销条件,请确保订单已确认,支付完成。", orderNum));

        }
        eycOrder.setStatus(OrderStatusEnum.COMPLETED.getCode());
        eycOrder.setVerificationTime(new Timestamp(new Date().getTime()));
        this.updateEycOrder(eycOrder);
        return eycOrder;
    }

    /**
     * @see com.chengyu.eyc.service.EycService#verificationOrders(java.util.List)
     */
    @Override
    public Boolean verificationOrders(List<String> orderNums) {
        for (String orderNum : orderNums) {
            this.verificationOrder(orderNum);
        }
        return Boolean.TRUE;
    }
    @Override
    public int searchAppointedDayPickupCarNum(String appointmentDt) {
        return this.eycOrderMapper.searchAppointedDayPickupCarNum(appointmentDt);
        
    }

   

}
